Micron Document
NexusPi Git Node


Displaying Raw • Download

native/main.cpp fc463eb4c579bbcd7340546e598044bd8345f3a5 (fc463eb4) Text, 6.59 KB

T8b949e// Copyright (C) 2026, microReticulum_Firmware contributors
T8b949e//
T8b949e// Portduino owns `main()` (see cores/portduino/main.cpp in the framework).
T8b949e// It defines `portduinoSetup()` as a weak symbol; overriding it here lets
T8b949e// us run config loading + EEPROM init before the Arduino sketch's setup()
T8b949e// is invoked.
T8b949e//
T8b949e// Sequence per Portduino's main:
T8b949e// portduinoCustomInit() -> empty (weak)
T8b949e// argp_parse(...) -> --fsroot etc.
T8b949e// mkdir($fsroot) -> VFS root directory
T8b949e// portduinoVFS->mountpoint(fsroot)
T8b949e// gpioInit()
T8b949e// portduinoSetup() <- this file
T8b949e// setup() <- Arduino sketch (RNode_Firmware.ino)
T8b949e// while (1) loop();

Tff7b72#Tff7b72include T8b949e"config.h"
Tff7b72#Tff7b72include T8b949e"EEPROMShim.h"
Tff7b72#Tff7b72include T8b949e"TCPHostInterface.h"

Tff7b72#Tff7b72include T8b949e<Arduino.h>T8b949e // brings in `extern HardwareSPI SPI;` declaration

Tff7b72#Tff7b72include T8b949e<cstdio>
Tff7b72#Tff7b72include T8b949e<cstdlib>
Tff7b72#Tff7b72include T8b949e<cstring>
Tff7b72#Tff7b72include T8b949e<string>
Tff7b72#Tff7b72include T8b949e<unistd.h>

T8b949e// strchrnul is a glibc extension that argp-standalone (on macOS, via
T8b949e// Homebrew) expects to find in libc. Apple's libc doesn't provide it,
T8b949e// so we define it here. POSIX-correct equivalent: return a pointer to
T8b949e// the first occurrence of c, or to the trailing NUL if c isn't found.
Tff7b72#Tff7b72ifdef __APPLE__
Tff7b72extern Ta5d6ff"Ta5d6ffCTa5d6ff" Tffa657charTff7b72* Te6edf3strchrnulTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3sTb4b4b4, Tffa657int Te6edf3cTb4b4b4) Tb4b4b4{
Tff7b72while Tb4b4b4(Tff7b72*Te6edf3s Tff7b72&Tff7b72& Tff7b72*Te6edf3s Tff7b72!Tff7b72= Tff7b72static_castTff7b72<Tffa657charTff7b72>Tb4b4b4(Te6edf3cTb4b4b4)Tb4b4b4) Tff7b72+Tff7b72+Te6edf3sTb4b4b4;
Tff7b72return Tff7b72const_castTff7b72<Tffa657charTff7b72*Tff7b72>Tb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif

T8b949e// Boards.h provides EEPROM_SIZE.
Tff7b72#Tff7b72include T8b949e"../Boards.h"

Tff7b72namespace T7ee787native_pinmap Tb4b4b4{
Tffa657void Td2a8ffapplyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657void Td2a8ffbind_linux_gpiosTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// no-op on macOS / cross_platform
Tffa657void Td2a8ffseed_eeprom_if_unprovisionedTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Defined in Utilities.h under the MODEM_RUNTIME branch. The native LoRa
T8b949e// factory in RNode_Firmware.ino setup() reads this to instantiate the
T8b949e// right concrete driver. Must be assigned before setup() runs.
Tff7b72extern Tffa657uint8_t Te6edf3current_modemTb4b4b4;

T8b949e// Forward declarations matching Config.h. We can't include Config.h
T8b949e// directly here because it contains file-scope variable definitions
T8b949e// (e.g. `uint8_t op_mode = MODE_HOST;`) that would cause multiple-
T8b949e// definition link errors when included from a second TU.
Tff7b72extern Tffa657uint8_t Te6edf3op_modeTb4b4b4;
Tff7b72#Tff7b72define FIRMWARE_MODE_TNC 0x12 T8b949e// mirrors MODE_TNC in Config.h

T8b949e// Portduino calls this before invoking the Arduino sketch's setup().
T8b949e// The symbol replaces Portduino's weak default (which has C++ linkage,
T8b949e// no extern "C") — match its signature exactly so the linker picks ours.
Tffa657void Td2a8ffportduinoSetupTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// 1) Load config from the default path (or a path supplied via env var).
Tff7b72const Tffa657charTff7b72* Te6edf3cfg_env Tff7b72= Te6edf3stdTff7b72:Tff7b72:Te6edf3getenvTb4b4b4(Ta5d6ff"Ta5d6ffMR_CONFIGTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3string Te6edf3cfg_path Tff7b72= Te6edf3cfg_env Tff7b72? Te6edf3cfg_env Tff7b72: Ta5d6ff"Ta5d6ffmicroreticulum.confTa5d6ff"Tb4b4b4;
Te6edf3native_configTff7b72:Tff7b72:Te6edf3loadTb4b4b4(Te6edf3cfg_pathTb4b4b4)Tb4b4b4;

T8b949e// 2) Optional --data-dir style override via env var.
Tff7b72const Tffa657charTff7b72* Te6edf3data_env Tff7b72= Te6edf3stdTff7b72:Tff7b72:Te6edf3getenvTb4b4b4(Ta5d6ff"Ta5d6ffMR_DATA_DIRTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3data_env Tff7b72&Tff7b72& Tff7b72*Te6edf3data_envTb4b4b4) Tb4b4b4{
Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3data_dir Tff7b72= Te6edf3data_envTb4b4b4;
Tb4b4b4}

T8b949e// 3) chdir to data dir so PosixFileSystem (microStore) and the EEPROM
T8b949e// image are scoped there. Portduino's own VFS root (--fsroot) is a
T8b949e// separate concern; we only care about cwd for our own persistence.
Tff7b72if Tb4b4b4(Te6edf3chdirTb4b4b4(Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3data_dirTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4, Ta5d6ff"Ta5d6ff[portduinoSetup] chdir(%s): %sTffea00\nTa5d6ff"Tb4b4b4,
Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3data_dirTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3stdTff7b72:Tff7b72:Te6edf3strerrorTb4b4b4(Te6edf3errnoTb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e// Continue anyway — relative paths will resolve to wherever
T8b949e// Portduino started us.
Tb4b4b4}

T8b949e// 4) Banner — make the mode obvious in the log.
Tff7b72#Tff7b72if !defined(LORA_TRANSPORT)
T8b949e// macOS launches headless: no Reticulum interfaces registered
T8b949e// (LORA_TRANSPORT is unflagged from [env:native-macos]).
T8b949e// Future UDPInterface support will land separately.
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4, Ta5d6ff"Ta5d6ff[native] no LoRa interface (LORA_TRANSPORT undefined)Tffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(PORTDUINO_LINUX_HARDWARE)
T8b949e// Linux native: real /dev/spidev + libgpiod backing.
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4, Ta5d6ff"Ta5d6ff[native] Linux hardware mode (spi=%s gpio=%s)Tffea00\nTa5d6ff"Tb4b4b4,
Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3spi_devTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3gpio_chipTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// 5) Pin map. apply() copies g_config.pin_* into the extern int pin_*
T8b949e// globals consulted by the modem driver. bind_linux_gpios() then
T8b949e// registers libgpiod-backed pins with Portduino (no-op on macOS).
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3applyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3bind_linux_gpiosTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// 5a) Surface the configured modem family to setup() so the native LoRa
T8b949e// factory can instantiate the right driver. Must precede setup().
Te6edf3current_modem Tff7b72= Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3modemTb4b4b4;
Tff7b72const Tffa657charTff7b72* Te6edf3modem_nameTb4b4b4;
Tff7b72switch Tb4b4b4(Te6edf3current_modemTb4b4b4) Tb4b4b4{
Tff7b72case T79c0ff0x01Tb4b4b4: Te6edf3modem_name Tff7b72= Ta5d6ff"Ta5d6ffSX1276Ta5d6ff"Tb4b4b4; Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x02Tb4b4b4: Te6edf3modem_name Tff7b72= Ta5d6ff"Ta5d6ffSX1278Ta5d6ff"Tb4b4b4; Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x03Tb4b4b4: Te6edf3modem_name Tff7b72= Ta5d6ff"Ta5d6ffSX1262Ta5d6ff"Tb4b4b4; Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x04Tb4b4b4: Te6edf3modem_name Tff7b72= Ta5d6ff"Ta5d6ffSX1280Ta5d6ff"Tb4b4b4; Tff7b72breakTb4b4b4;
Tff7b72defaultTff7b72: Te6edf3modem_name Tff7b72= Ta5d6ff"Ta5d6ffUNKNOWNTa5d6ff"Tb4b4b4; Tff7b72breakTb4b4b4;
Tb4b4b4}
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4, Ta5d6ff"Ta5d6ff[native] modem = %s (0x%02X)Tffea00\nTa5d6ff"Tb4b4b4, Te6edf3modem_nameTb4b4b4, Te6edf3current_modemTb4b4b4)Tb4b4b4;

T8b949e// 5b) KISS-over-TCP host transport. The embedded firmware's USB-serial
T8b949e// KISS channel is replaced on native by a localhost TCP server.
T8b949e// A failure to bind isn't fatal — the daemon keeps running like
T8b949e// an embedded RNode with no USB cable plugged in. kiss_tcp_public
T8b949e// opts into binding on 0.0.0.0; defaults to loopback.
Te6edf3native_kiss_tcpTff7b72:Tff7b72:Te6edf3initTb4b4b4(Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3kiss_tcp_portTb4b4b4,
Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3kiss_tcp_publicTb4b4b4)Tb4b4b4;

T8b949e// 6) Bind a SimSPIChip as a safety net. With LORA_TRANSPORT removed,
T8b949e// the modem driver no longer initiates SPI activity, but Portduino's
T8b949e// HardwareSPI::transfer() will assert(spiChip) if anything else
T8b949e// (a stray indirect call, a thread, etc.) reaches the SPI subsystem.
T8b949e// SPI.begin() creates a SimSPIChip on cross_platform / non-Linux.
Te6edf3SPITb4b4b4.Te6edf3beginTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// 7) EEPROM image (file-backed shim — see native/EEPROMShim.h).
Te6edf3EEPROMTb4b4b4.Te6edf3beginTb4b4b4(Te6edf3EEPROM_SIZETb4b4b4)Tb4b4b4;
Te6edf3native_pinmapTff7b72:Tff7b72:Te6edf3seed_eeprom_if_unprovisionedTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// 8) Force TNC mode on the native daemon. The embedded firmware flips
T8b949e// op_mode to MODE_TNC only when `hw_ready && eeprom_have_conf()`,
T8b949e// which requires real radio hardware. On the native daemon — where
T8b949e// we may run without a connected modem (or where the modem driver
T8b949e// is fully bypassed on macOS via LORA_TRANSPORT) — we mark the
T8b949e// daemon as TNC explicitly so the Reticulum Transport runs in
T8b949e// enabled mode rather than the host-protocol fallback.
Te6edf3op_mode Tff7b72= Te6edf3FIRMWARE_MODE_TNCTb4b4b4;
Tb4b4b4}

Served by rngit 1.5.3 - Generated in 0.02s